/*
 @Name: page插件
 @Author: ray
 @License: MIT
 */
; rayui.define(function (exports, undef) {
    "use strict";

    var $ = rayui.$,
        $win = $(window),
        $doc = $(document),
        plugName = "pagescroll",
        scrollinfo = {},
        DealClass = function (options) {
            var that = this;
            this.options = options;
            //elem不能为document
            if ($(options.elem).is($doc)) return;

            options.$elem = $(options.elem);
            if (options.$elem.length !== 1) return;

            $("html,body").addClass('htmlbody');
            options.$elem.addClass('pagescroll unselect').height($win.height() - options.$elem.offset().top);

            //初始化
            options.down.use && utils.initDown.call(that);
            utils.addEvents.call(that);

            //下拉首次刷新
            if (options.down.first) {
                setTimeout(function () {
                    options.$tip.css({
                        opacity: 1,
                        height: options.down.gap + "px"
                    });
                    utils.callbackDown.call(that);
                }, 0);
            }
            return this;
        };

    DealClass.option = {
        noMoreCount: 5,//只有当总数据条数小于noMoreCount时才会显示没有数据
        noMoreDataTip: "--没有更多数据了--",
        //分页信息
        page: {
            cur: 0,//当前页 默认0，回调之前会加1;
            limit: 10//每页数据条数,默认10
        },
        //使用下拉刷新
        down: {
            use: true,//是否启用
            first: true,//首次是否初始化加载数据
            gap: 100,//下拉缺口，下拉100px松开刷新
            textInGap: '下拉刷新', // 下拉距离在gap范围内的提示
            textOutGap: '释放更新', // 下拉距离大于gap范围的提示
            textLoading: '加载中···', // 加载中的提示
            htmlTip: '<i class="ra pagescroll-down-icon"></i><span class="pagescroll-down-text"></span>', // 下拉提示，如果自定义，一定要有pagescroll-down-text样式
        },
        //使用上拉加载
        up: {
            use: true,//是否启用
            gap: 100,//上拉缺口，距离底部100px时触发回调
            toTopBtn: true,//回到顶部按钮
            toTopGap: 200,//当数据内容超出视野200px高度时才会显示回到顶部按钮
            toTopDuration: 300,//回到顶部时长动画时间
            textLoading: '正在加载', // 加载中的提示
            htmlTip: '<i class="ra pagescroll-down-icon pagescroll-down-animate"></i><span class="pagescroll-up-text"></span>', // 上拉提示，如果自定义，一定要有pagescroll-up-text样式
        }
    };

    var utils = {
        initDown: function () {
            var that = this,
                options = that.options,
                opt_down = options.down,
                $elem = options.$elem,
                $tip = options.$tip = $('<div class="pagescroll-down-tip"/>').prependTo($elem),
                $tipcontent = $('<div class="pagescroll-down-tipcontent"/>').append(opt_down.htmlTip).appendTo($tip);

            options.$tipicon = $tipcontent.find('.pagescroll-down-icon');
            options.$tiptext = $tipcontent.find(".pagescroll-down-text").html(opt_down.textInGap);

        },
        initUp: function () {
            var that = this,
                options = that.options,
                opt_up = options.up,
                $elem = options.$elem,
                $tipcontent = $('<div class="pagescroll-up-tipcontent"/>').append(opt_up.htmlTip);

            //添加到容器
            opt_up.$tip = $('<div class="pagescroll-up-tip"/>').append($tipcontent).appendTo($elem);
            $tipcontent.find(".pagescroll-up-text").html(opt_up.textLoading);
        },
        hideDown: function (callback) {
            var that = this,
                options = that.options,
                $tip = options.$tip;

            scrollinfo.down = false;
            if ($tip.height() === 0) {
                callback && callback();
            } else {
                callback ? $tip.animate({ height: 0 }, 300, callback) : $tip.height(0);
            }
        },
        hideUp: function (callback) {
            var that = this,
                options = that.options,
                opt_up = options.up;

            opt_up.$tip != null && opt_up.$tip.remove();
            opt_up.$tip = null;
        },
        touchstart_mousedown: function (e) {
            var that = this,
                options = that.options,
                $elem = options.$elem;

            scrollinfo.start = true;
            scrollinfo.Y = e.touches ? e.touches[0].pageY : e.pageY;
            scrollinfo.scrollTop = $elem.scrollTop();
        },
        touchmove_mousemove: function (e) {
            var that = this,
                options = that.options;
            if (options.ajaxloading) return;
            //是否显示回到顶部按钮
            utils.showToTopBtn.call(that);
            if (!scrollinfo.start) return;

            var opt_down = options.down,
                opt_up = options.up,
                elemDom = options.$elem[0],
                $elem = options.$elem,
                $tip = options.$tip,
                $tipicon = options.$tipicon,
                $tiptext = options.$tiptext,
                moveY = (e.touches ? e.touches[0].pageY : e.pageY) - scrollinfo.Y;

            utils.showToTopBtn.call(that);
            //上拉
            if (moveY < 0) {
                scrollinfo.down = false;

                if (opt_up.use) {
                    //如果上拉进入gap间隔内直接触发回调
                    var bottomGap = elemDom.scrollHeight - $elem.height() - $elem.scrollTop();
                    if (bottomGap <= opt_up.gap && !opt_up.$tip) {
                        //容器添加加载中
                        utils.initUp.call(that);
                        //回调
                        utils.callbackUp.call(that);
                    }
                }
            } else {
                if (!opt_down.use || $elem.scrollTop() != 0) return;
                //下拉
                var height = moveY;
                //>80则停止效果
                if (moveY > opt_down.gap) {
                    scrollinfo.down = true;
                    //修改提示语
                    $tiptext.html(opt_down.textOutGap);
                    height = opt_down.gap + (moveY - opt_down.gap) * 0.3;
                } else {
                    scrollinfo.down = false;
                    //修改提示语
                    $tiptext.html(opt_down.textInGap);
                }

                var tipH = (height - scrollinfo.scrollTop) * 0.9,
                    rotate = height / opt_down.gap * 100;
                //$tip.height();
                $tip.css({
                    opacity: tipH / 40,//淡入，高度达到40px时完全显示
                    height: tipH + "px"
                });
                $tipicon.css({
                    transform: 'rotate(' + rotate + 'deg)',
                    webkitTransform: 'rotate(' + rotate + 'deg)'
                });
                e.cancelable && e.preventDefault();
            }
        },
        touchend_mouseup: function (e) {
            var that = this,
                options = that.options,
                opt_down = options.down,
                $tipicon = options.$tipicon,
                $tiptext = options.$tiptext;

            if (options.ajaxloading) return;

            scrollinfo.start = false;
            //下拉松开
            if (opt_down.use) {
                //如果下拉大于gap触发回调，否则直接隐藏
                if (scrollinfo.down) {
                    //移除上拉加载更多提示
                    utils.hideUp.call(that);
                    utils.callbackDown.call(that);
                }
                else {
                    utils.hideDown.call(that, function () {
                        $tiptext.html(opt_down.textInGap);
                        $tipicon.removeClass('pagescroll-down-animate');
                    });
                }

            }

        },
        scroll: function (e) {
            var that = this;
            //是否显示回到顶部按钮
            utils.showToTopBtn.call(that);

            var options = that.options,
                opt_up = options.up,
                elemDom = options.$elem[0],
                $elem = options.$elem;


            if (opt_up.use) {
                //如果上拉进入gap间隔内直接触发回调
                var bottomGap = elemDom.scrollHeight - $elem.height() - $elem.scrollTop();
                if (bottomGap <= opt_up.gap && !opt_up.$tip && !options.ajaxloading) {
                    //容器添加加载中
                    utils.initUp.call(that);
                    //回调
                    utils.callbackUp.call(that)
                }
            }
        },
        callbackDown: function () {
            var that = this,
                options = that.options,
                opt_down = options.down,
                $tipicon = options.$tipicon,
                $tiptext = options.$tiptext;

            if (options.ajaxloading) return;
            options.ajaxloading = true;
            //重置分页页码
            options.page.cur = 1;
            $tiptext.html(opt_down.textLoading);
            $tipicon.addClass('pagescroll-down-animate');
            typeof opt_down.callback === "function" && opt_down.callback();
        },
        callbackUp: function () {
            var that = this,
                options = that.options,
                opt_up = options.up;

            if (options.ajaxloading) return;
            options.ajaxloading = true;
            //分页页码+1
            options.page.cur++;
            typeof opt_up.callback === "function" && opt_up.callback(options.page);
        },
        endDown: function (curLength, totalLength) {
            var that = this,
                options = that.options,
                opt_down = options.down,
                $tipicon = options.$tipicon,
                $tiptext = options.$tiptext;

            options.ajaxloading = false;
            utils.hideDown.call(that, function () {
                $tiptext.html(opt_down.textInGap);
                $tipicon.removeClass('pagescroll-down-animate');
            });
            utils.showToTopBtn.call(that);
            utils.showNoMoreData.call(that, curLength, totalLength);
        },
        endUp: function (curLength, totalLength) {
            var that = this,
                options = that.options;

            options.ajaxloading = false;
            utils.hideUp.call(that);
            utils.showToTopBtn.call(that);
            utils.showNoMoreData.call(that, curLength, totalLength);
        },
        showToTopBtn: function () {
            var that = this,
                options = that.options,
                opt_up = options.up,
                $elem = options.$elem;

            if (!opt_up.toTopBtn) return;

            if (!opt_up.$toTopBtn) {
                opt_up.$toTopBtn = $('<a href="javascript:void(0)" class="pagescroll-totopbtn" title="回到顶端"></a>').appendTo($('body'));
                opt_up.$toTopBtn.click(function () {
                    $elem.animate({ scrollTop: '0px' }, options.toTopDuration, function () {
                        opt_up.$toTopBtn.hide();
                    });
                });
            }

            $elem.scrollTop() > opt_up.toTopGap ? opt_up.$toTopBtn.show() : opt_up.$toTopBtn.hide();

        },
        showNoMoreData: function (curLength, totalLength) {
            var that = this,
                options = that.options,
                page = options.page,
                dataCount = (page.cur - 1) * page.limit + curLength,
                opt_up = options.up,
                $elem = options.$elem;

            //只可能等于不可能大于
            if (page.cur == 1 && curLength >= options.noMoreCount && curLength >= totalLength
                || page.cur > 1 && dataCount >= totalLength) {
                //显示
                opt_up.$tip = $('<div class="pagescroll-up-tip"><div class="pagescroll-up-tipcontent"><span class="pagescroll-up-text">' + options.noMoreDataTip + '</span></div></div>').appendTo($elem);
            }
        },
        addEvents: function () {
            var that = this,
                options = that.options,
                elemDom = $(options.elem)[0];

            $(options.elem).on("mousedown", function (e) { utils.touchstart_mousedown.call(that, e) });
            $(options.elem).on("mousemove", function (e) { utils.touchmove_mousemove.call(that, e) });
            $(options.elem).on("mouseup", function (e) { utils.touchend_mouseup.call(that, e) });
            //$(options.elem).on("mouseleave", function () { rayui.log("mouseleave") });
            options.up.use && $(options.elem).on("scroll", function (e) { utils.scroll.call(that, e) });

            elemDom.addEventListener('touchstart', function (e) { utils.touchstart_mousedown.call(that, e) });
            elemDom.addEventListener('touchmove', function (e) { utils.touchmove_mousemove.call(that, e) }, { passive: false });
            elemDom.addEventListener('touchend', function (e) { utils.touchend_mouseup.call(that, e) });

            //$(options.elem).on("touchcancel", function () { rayui.log("touchcancel") });

        }
    }

    DealClass.prototype = {
        endDown: function (curLength, totalLength) {
            utils.endDown.call(this, curLength, totalLength);
        },
        endUp: function (curLength, totalLength) {
            utils.endUp.call(this, curLength, totalLength);
        }
    };

    var pagepg = {
        options: DealClass.option,
        render: function (elem, options) {
            options = options || {};
            options = $.extend(true, { elem: elem }, DealClass.option, options, $.isPlainObject(elem) && elem);
            return new DealClass(options);
        }
    };

    exports(plugName, pagepg);
}, rayui.jsAsync());
